/**
 * 
 */
package com.maywide.jdp.system.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.maywide.jdp.core.exception.AppException;
import com.maywide.jdp.core.vo.Context;
import com.maywide.jdp.core.vo.Page;
import com.maywide.jdp.system.annotation.JSON;
import com.maywide.jdp.system.bean.MenuBean;
import com.maywide.jdp.system.entities.Menu;
import com.maywide.jdp.system.entities.Role;
import com.maywide.jdp.system.utils.JSONEditor;
import com.maywide.jdp.system.vo.MenuCheckedTree;
import com.maywide.jdp.system.vo.MenuTree;
import com.maywide.jdp.system.vo.MenuVO;
import com.maywide.jdp.system.vo.SubMenuVO;

/**
 * 菜单管理Service
 * 
 * @author luoyang
 * @version 1.0
 * @since JDK1.6
 */
@Controller("menuService")
public class MenuServiceImpl implements MenuService {
	private static final String APP_TYPE_BASE = "base";
	private static final String APP_TYPE_ROLES = "roles";
	/**
	 * 菜单Bean接口
	 */
	private MenuBean bean = null;

	/**
	 * @param bean
	 *            the bean to set
	 */
	@Autowired
	@Qualifier("menuBean")
	public void setBean(MenuBean bean) {
		this.bean = bean;
	}

	@JSON
	@RequestMapping(value = "/system/menu/insert.json")
	@Override
	public Menu insert(@RequestParam(value = "menu") Menu menu,
			HttpServletRequest request, HttpServletResponse response,
			HttpSession session) throws Exception {
		bean.insert(menu);
		return menu;
	}

	@JSON
	@RequestMapping(value = "/system/menu/update.json")
	@Override
	public Menu update(@RequestParam(value = "menu") Menu menuVO,
			HttpServletRequest request, HttpServletResponse response,
			HttpSession session) throws Exception {
		String id = menuVO.getId();
		Menu menu = (Menu) bean.load(id);

		// 取得不可改变属性
		Menu parent = menu.getParent();
		List<Menu> subs = menu.getSubs();

		menuVO.setParent(parent);
		menuVO.setSubs(subs);
		BeanUtils.copyProperties(menuVO, menu);

		bean.update(menu);
		return menu;
	}

	@JSON
	@RequestMapping(value = "/system/menu/updateApp.json")
	@Override
	public Menu updateApp(@RequestParam(value = "menu") Menu menuVO,
			@RequestParam(value = "appType") String appType,
			HttpServletRequest request, HttpServletResponse response,
			HttpSession session) throws Exception {
		String id = menuVO.getId();

		if (appType.equals(APP_TYPE_BASE)) {
			// 取得不可改变属性
			Menu menu = (Menu) bean.load(id);
			Menu parent = menu.getParent();
			List<Menu> subs = menu.getSubs();
			List<Role> roles = menu.getRoles();

			menuVO.setParent(parent);
			menuVO.setSubs(subs);
			menuVO.setRoles(roles);
			BeanUtils.copyProperties(menuVO, menu);

			bean.update(menu);
			return menu;
		} else if (appType.equals(APP_TYPE_ROLES)) {
			List<Role> roles = menuVO.getRoles();
			Menu menu = (Menu) bean.load(id);
			menu.setRoles(roles);
			bean.update(menu);
			return menu;
		} else {
			throw new AppException("未知的应用类型!");
		}
	}

	@JSON
	@RequestMapping(value = "/system/menu/load.json")
	@Override
	public Menu load(@RequestParam(value = "id") String id,
			HttpServletRequest request, HttpServletResponse response,
			HttpSession session) throws Exception {
		Menu menu = (Menu) bean.load(id);
		return menu;
	}

	@RequestMapping(value = "/system/menu/lock.json")
	@Override
	public void lock(@RequestParam(value = "id") String id,
			HttpServletRequest request, HttpServletResponse response,
			HttpSession session) throws Exception {
		bean.lock(id);
	}

	@RequestMapping(value = "/system/menu/unlock.json")
	@Override
	public void unlock(@RequestParam(value = "id") String id,
			HttpServletRequest request, HttpServletResponse response,
			HttpSession session) throws Exception {
		bean.unlock(id);
	}

	@RequestMapping(value = "/system/menu/move.json")
	@Override
	public void move(@RequestParam(value = "ids") List<String> ids,
			@RequestParam(value = "targetID") String parentID,
			HttpServletRequest request, HttpServletResponse response,
			HttpSession session) throws Exception {
		bean.move(ids, parentID);
	}

	@JSON
	@RequestMapping(value = "/system/menu/page.json")
	public Page page(
			@RequestParam(value = "first", defaultValue = "0") int first,
			@RequestParam(value = "limit", defaultValue = "20") int limit,
			@RequestParam(value = "sort", required = false) String sort,
			@RequestParam(value = "dir", required = false) String dir,
			@RequestParam(value = "parentID", required = false) String parentID,
			@RequestParam(value = "noParentID", required = false) String noParentID,
			@RequestParam(value = "key", required = false) String key,
			@RequestParam(value = "active", required = false) String active,
			HttpServletRequest request, HttpServletResponse response,
			HttpSession session) throws Exception {
		Map<String, Object> conditions = new HashMap<String, Object>();

		if (key != null) {
			key = new StringBuffer("%").append(key).append("%").toString();
			conditions.put("key", key);
		}

		if (active != null)
			conditions.put("active", Boolean.parseBoolean(active));

		if (parentID != null && !"menu_root".equals(parentID))
			conditions.put("parentID", parentID);
		else
			conditions.put("noParentID", null);

		Context context = (Context) session.getAttribute("context");
		String[] roleIDs = context.getRoleIDs();
		if (roleIDs != null)
			conditions.put("roleIDs", roleIDs);

		return bean.page(first, limit, sort, dir, conditions, null);
	}

	@JSON
	@RequestMapping(value = "/system/menu/tree.json")
	@SuppressWarnings("unchecked")
	public List<MenuTree> tree(
			@RequestParam(value = "parentID") String parentID,
			@RequestParam(value = "rootID", required = false) String rootID,
			HttpServletRequest request, HttpServletResponse response,
			HttpSession session) throws Exception {
		Map<String, Object> conditions = new HashMap<String, Object>();

		if (parentID != null && !"menu_root".equals(parentID))
			conditions.put("parentID", parentID);
		else
			conditions.put("noParentID", null);

		if (rootID != null)
			conditions.put("rootID", rootID);

		Context context = (Context) session.getAttribute("context");
		String[] roleIDs = context.getRoleIDs();
		if (roleIDs != null)
			conditions.put("roleIDs", roleIDs);

		return bean.tree(conditions);
	}

	@JSON
	@RequestMapping(value = "/system/menu/treeGrid.json")
	public List<MenuCheckedTree> treeGrid(
			@RequestParam(value = "parentID") String parentID,
			@RequestParam(value = "rootID", required = false) String rootID,
			@RequestParam(value = "roleID") String roleID,
			HttpServletRequest request, HttpServletResponse response,
			HttpSession session) throws Exception {
		Map<String, Object> conditions = new HashMap<String, Object>();

		if (parentID != null && !"menu_root".equals(parentID))
			conditions.put("parentID", parentID);
		else
			conditions.put("noParentID", null);

		if (rootID != null)
			conditions.put("rootID", rootID);

		if (roleID != null)
			conditions.put("roleID", roleID);

		Context context = (Context) session.getAttribute("context");
		String[] roleIDs = context.getRoleIDs();
		if (roleIDs != null)
			conditions.put("roleIDs", roleIDs);

		return bean.treeGrid(conditions);
	}

	@JSON
	@RequestMapping("/getStartMenus.json")
	@Override
	public List<MenuVO> getStartMenus(HttpServletRequest request,
			HttpServletResponse response, HttpSession session) throws Exception {
		Context context = (Context) session.getAttribute("context");
		List<Menu> menus = bean.getStartMenus(context);
		List<MenuVO> menuVOs = selectMenuVO(menus, null);
		return menuVOs;
	}

	private List<MenuVO> selectMenuVO(List<Menu> menus, String parentID)
			throws Exception {
		List<MenuVO> menuList = null;
		if (menus != null && !menus.isEmpty()) {
			for (Menu menu : menus) {
				String id = menu.getId();
				String strParentID = menu.getParentID();
				if ((parentID == null && strParentID == null)
						|| (parentID != null && parentID.equals(strParentID))) {
					if (menuList == null)
						menuList = new ArrayList<MenuVO>();

					MenuVO menuVO = new MenuVO();
					BeanUtils.copyProperties(menu, menuVO);

					List<MenuVO> items = selectMenuVO(menus, id);
					if (items != null && !items.isEmpty()) {
						SubMenuVO subMenu = new SubMenuVO();
						subMenu.setItems(items);
						menuVO.setMenu(subMenu);
					}

					menuList.add(menuVO);
				}
			}
		}
		return menuList;
	}

	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		binder.registerCustomEditor(MenuVO.class, new JSONEditor(MenuVO.class));
		binder.registerCustomEditor(Menu.class, new JSONEditor(Menu.class));
	}

}
